%%--- coding:utf-8 ---
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% File Name: mc_worker_api_test
%%% Created on : 2024/5/27 7:40
%%% @author Gaylen 252323463@qq.com
%%% @copyright (C) 2024, freedom
%%% @doc
%%%
%%% @end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-module(mc_worker_api_test).
-author("Gaylen").
-include_lib("eunit/include/eunit.hrl").

-define(MONGO_TEST_POOL, 'mongo_test_pool').

init_test() ->
    mongodb_driver:start(undefined, undefined),
    ConnectArgs = [
        {host, ""},
        {port, 27017},
        {database, <<"test">>},
        {user, <<"root">>},
        {password, <<"">>},
        {auth_source, <<"admin">>}
    ],
    mc_pool_api:start_pool(?MONGO_TEST_POOL, ConnectArgs).

%%insert_test() ->
%%    ConnectArgs = [
%%        {host, ""},
%%        {port, 27017},
%%        {database, <<"test">>},
%%        {user, <<"root">>},
%%        {password, <<"">>},
%%        {auth_source, <<"admin">>}
%%    ],
%%    {ok, ConnPid} = mc_worker_api:connect(ConnectArgs),
%%    Doc = #{
%%        <<"_id">> => 1,
%%        <<"id">> => 1,
%%        <<"name">> => <<"t01">>,
%%        <<"exp">> => 101.0
%%    },
%%    _Result = mc_worker_api:insert(ConnPid, <<"test">>, <<"role">>, Doc),
%%    Docs = [#{
%%        <<"_id">> => 2,
%%        <<"id">> => 2,
%%        <<"name">> => <<"t02">>,
%%        <<"exp">> => 102.0
%%    },#{
%%        <<"_id">> => 3,
%%        <<"id">> => 3,
%%        <<"name">> => <<"t03">>,
%%        <<"exp">> => 103.0
%%    }],
%%    Result2 = mc_worker_api:insert(ConnPid, <<"test">>, <<"role">>, Docs),
%%    file:write_file("test.log", io_lib:format("~p", [Result2])).

%%update_test() ->
%%    ConnectArgs = [
%%        {host, ""},
%%        {port, 27017},
%%        {database, <<"test">>},
%%        {user, <<"root">>},
%%        {password, <<"">>},
%%        {auth_source, <<"admin">>}
%%    ],
%%    {ok, ConnPid} = mc_worker_api:connect(ConnectArgs),
%%    SelectorDoc = #{
%%        <<"id">> => 1
%%    },
%%    UpdateDoc = #{
%%        <<"$set">> => #{
%%            <<"name">> => <<"uutest01">>
%%        }
%%    },
%%    Result = mc_worker_api:update(ConnPid, <<"test">>, <<"role">>, SelectorDoc, UpdateDoc, true, false),
%%    file:write_file("test.log", io_lib:format("~p", [Result])).

%%delete_test() ->
%%    ConnectArgs = [
%%        {host, ""},
%%        {port, 27017},
%%        {database, <<"test">>},
%%        {user, <<"root">>},
%%        {password, <<"">>},
%%        {auth_source, <<"admin">>}
%%    ],
%%    {ok, ConnPid} = mc_worker_api:connect(ConnectArgs),
%%    SelectorDoc = #{
%%        <<"id">> => 3
%%    },
%%    Result = mc_worker_api:delete_one(ConnPid, <<"test">>, <<"role">>, SelectorDoc),
%%    file:write_file("test.log", io_lib:format("~p", [Result])).

%%find_one_test() ->
%%    ConnectArgs = [
%%        {host, ""},
%%        {port, 27017},
%%        {database, <<"test">>},
%%        {user, <<"root">>},
%%        {password, <<"">>},
%%        {auth_source, <<"admin">>}
%%    ],
%%    {ok, ConnPid} = mc_worker_api:connect(ConnectArgs),
%%    SelectorDoc = #{
%%        <<"id">> => 1
%%    },
%%    Result = mc_worker_api:find_one(ConnPid, <<"test">>, <<"role">>, SelectorDoc),
%%    file:write_file("test.log", io_lib:format("~p", [Result])).

%%ensure_index_test() ->
%%    ConnectArgs = [
%%        {host, ""},
%%        {port, 27017},
%%        {database, <<"test">>},
%%        {user, <<"root">>},
%%        {password, <<"">>},
%%        {auth_source, <<"admin">>}
%%    ],
%%    {ok, ConnPid} = mc_worker_api:connect(ConnectArgs),
%%    Result = mc_worker_api:ensure_index(ConnPid, <<"test">>, <<"role">>, {<<"id">>,1}, true),
%%    file:write_file("test.log", io_lib:format("~p", [Result])).

%%ping_test() ->
%%    ConnectArgs = [
%%        {host, ""},
%%        {port, 27017},
%%        {database, <<"test">>},
%%        {user, <<"root">>},
%%        {password, <<"">>},
%%        {auth_source, <<"admin">>}
%%    ],
%%    {ok, ConnPid} = mc_worker_api:connect(ConnectArgs),
%%    Result = mc_worker_api:ping(ConnPid, <<"test111">>),
%%    file:write_file("test.log", io_lib:format("~p", [Result])).

%%find_and_modify_test() ->
%%    ConnectArgs = [
%%        {host, ""},
%%        {port, 27017},
%%        {database, <<"test">>},
%%        {user, <<"root">>},
%%        {password, <<"">>},
%%        {auth_source, <<"admin">>}
%%    ],
%%    {ok, ConnPid} = mc_worker_api:connect(ConnectArgs),
%%    Selector = #{
%%        <<"id">> => 5
%%    },
%%    UpdateDoc = #{
%%        <<"$inc">> => #{
%%            <<"exp">> => 1
%%        }
%%    },
%%    Result = mc_worker_api:find_and_modify(ConnPid, <<"test">>, <<"role">>, Selector, UpdateDoc, #{<<"id">>=>1,<<"exp">>=>1}, false),
%%    file:write_file("test.log", io_lib:format("~p", [Result])).

%%count_test() ->
%%    ConnectArgs = [
%%        {host, ""},
%%        {port, 27017},
%%        {database, <<"test">>},
%%        {user, <<"root">>},
%%        {password, <<"">>},
%%        {auth_source, <<"admin">>}
%%    ],
%%    {ok, ConnPid} = mc_worker_api:connect(ConnectArgs),
%%    Selector = #{
%%    },
%%    Result = mc_worker_api:count(ConnPid, <<"test">>, <<"role">>, Selector),
%%    file:write_file("test.log", io_lib:format("~p", [Result])).

%%insert_batch_test() ->
%%    ConnectArgs = [
%%        {host, ""},
%%        {port, 27017},
%%        {database, <<"test">>},
%%        {user, <<"root">>},
%%        {password, <<"">>},
%%        {auth_source, <<"admin">>}
%%    ],
%%    {ok, ConnPid} = mc_worker_api:connect(ConnectArgs),
%%    insert_first_batch(ConnPid, 1, 100, 1000).
%%insert_first_batch(_ConnPid, Cur, _NextCur, Max) when Cur >= Max ->
%%    ok;
%%insert_first_batch(ConnPid, Cur, NextCur, Max) ->
%%    Docs = generate_insert_docs(Cur, NextCur, []),
%%    Result = mc_worker_api:insert(ConnPid, <<"test">>, <<"role">>, Docs),
%%    file:write_file("test.log", io_lib:format("~p", [Result])),
%%    insert_first_batch(ConnPid, NextCur, min(NextCur + 100, Max), Max).
%%generate_insert_docs(Cur, Max, DocsAcc) when Cur >= Max ->
%%    DocsAcc;
%%generate_insert_docs(Cur, Max, DocsAcc) ->
%%    CurStr = integer_to_binary(Cur),
%%    Doc = #{
%%        <<"_id">> => Cur,
%%        <<"id">> => Cur,
%%        <<"name">> => <<"name_", CurStr/binary>>,
%%        <<"exp">> => Cur + 0.1
%%    },
%%    generate_insert_docs(Cur + 1, Max, [Doc | DocsAcc]).

%%find_test() ->
%%    ConnectArgs = [
%%        {host, ""},
%%        {port, 27017},
%%        {database, <<"test">>},
%%        {user, <<"root">>},
%%        {password, <<"">>},
%%        {auth_source, <<"admin">>}
%%    ],
%%    {ok, ConnPid} = mc_worker_api:connect(ConnectArgs),
%%    SelectorDoc = #{},
%%    {ok, _FirstBatchs, CursorPid} = mc_worker_api:find(ConnPid, <<"test">>, <<"role">>, SelectorDoc, #{}, 0, 100),
%%%%    file:write_file("test.log", io_lib:format("~p", [CursorPid])),
%%    next_doc(CursorPid, 100),
%%    mc_cursor:close(CursorPid).
%%
%%next_doc(CursorPid, BatchSize) ->
%%    case mc_cursor:next(CursorPid, BatchSize) of
%%        {ok, []} -> ok;
%%        {ok, NextBatchs} ->
%%            file:write_file("test.log", io_lib:format("~p~n~n~p", [BatchSize, NextBatchs])),
%%            next_doc(CursorPid, BatchSize);
%%        _ -> ok
%%    end.

ensure_index_pool_test() ->
    Result = mc_pool_api:ensure_index(?MONGO_TEST_POOL, <<"test">>, <<"role">>, {<<"id">>,1}, true),
    file:write_file("test.log", io_lib:format("ensure_index_pool_test: ~p", [Result])).

delete_all_pool_test() ->
    SelectorDoc = #{
    },
    Result = mc_pool_api:delete_all(?MONGO_TEST_POOL, <<"test">>, <<"role">>, SelectorDoc),
    file:write_file("test.log", io_lib:format("delete_pool_test: ~p", [Result])).

insert_pool_test() ->
    Doc = #{
        <<"_id">> => 1,
        <<"id">> => 1,
        <<"name">> => <<"t01">>,
        <<"exp">> => 101.0
    },
    _Result = mc_pool_api:insert(?MONGO_TEST_POOL, <<"test">>, <<"role">>, Doc),
    Docs = [#{
        <<"_id">> => 2,
        <<"id">> => 2,
        <<"name">> => <<"t02">>,
        <<"exp">> => 102.0
    },#{
        <<"_id">> => 3,
        <<"id">> => 3,
        <<"name">> => <<"t03">>,
        <<"exp">> => 103.0
    }],
    Result2 = mc_pool_api:insert(?MONGO_TEST_POOL, <<"test">>, <<"role">>, Docs),
    file:write_file("test.log", io_lib:format("~p", [Result2])).

update_pool_test() ->
    SelectorDoc = #{
        <<"id">> => 1
    },
    UpdateDoc = #{
        <<"$set">> => #{
            <<"name">> => <<"uutest01">>
        }
    },
    Result = mc_pool_api:update(?MONGO_TEST_POOL, <<"test">>, <<"role">>, SelectorDoc, UpdateDoc, true, false),
    file:write_file("test.log", io_lib:format("update_pool_test: ~p", [Result])).

find_one_pool_test() ->
    SelectorDoc = #{
        <<"id">> => 1
    },
    Result = mc_pool_api:find_one(?MONGO_TEST_POOL, <<"test">>, <<"role">>, SelectorDoc),
    file:write_file("test.log", io_lib:format("find one: ~p", [Result])).

delete_pool_test() ->
    SelectorDoc = #{
        <<"id">> => 1
    },
    Result = mc_pool_api:delete_one(?MONGO_TEST_POOL, <<"test">>, <<"role">>, SelectorDoc),
    file:write_file("test.log", io_lib:format("delete_pool_test: ~p", [Result])).

find_and_modify_pool_test() ->
    Selector = #{
        <<"id">> => 1
    },
    UpdateDoc = #{
        <<"$inc">> => #{
            <<"exp">> => 1
        }
    },
    Result = mc_pool_api:find_and_modify(?MONGO_TEST_POOL, <<"test">>, <<"role">>, Selector, UpdateDoc, #{<<"id">>=>1,<<"exp">>=>1}, false),
    file:write_file("test.log", io_lib:format("find_and_modify_pool_test: ~p", [Result])).

count_pool_test() ->
    Selector = #{
    },
    Result = mc_pool_api:count(?MONGO_TEST_POOL, <<"test">>, <<"role">>, Selector),
    file:write_file("test.log", io_lib:format("count_pool_test: ~p", [Result])).

insert_batch_1_pool_test() ->
    mc_pool_api:delete_all(?MONGO_TEST_POOL, <<"test">>, <<"role">>, #{}),
    insert_first_batch(?MONGO_TEST_POOL, 1, 100, 10000).

insert_batch_2_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 10000, 10100, 20000).

insert_batch_3_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 20000, 20100, 30000).

insert_batch_4_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 30000, 30100, 40000).

insert_batch_5_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 40000, 40100, 50000).

insert_batch_6_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 50000, 50100, 60000).

insert_batch_7_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 60000, 60100, 70000).

insert_batch_8_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 70000, 70100, 80000).

insert_batch_9_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 80000, 80100, 90000).

insert_batch_10_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 90000, 90100, 100000).

insert_batch_11_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 100000, 100100, 110000).

insert_batch_12_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 110000, 110100, 120000).

insert_batch_13_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 120000, 120100, 130000).

insert_batch_14_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 130000, 130100, 140000).

insert_batch_15_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 140000, 140100, 150000).

insert_batch_16_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 150000, 150100, 160000).

insert_batch_17_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 160000, 160100, 170000).

insert_batch_18_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 170000, 170100, 180000).

insert_batch_19_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 180000, 180100, 190000).

insert_batch_20_pool_test() ->
    insert_first_batch(?MONGO_TEST_POOL, 190000, 190100, 200000).

insert_first_batch(_RegName, Cur, _NextCur, Max) when Cur >= Max ->
    ok;
insert_first_batch(ConnPid, Cur, NextCur, Max) ->
    Docs = generate_insert_docs_for_pool(Cur, NextCur, []),
    Result = mc_pool_api:insert(ConnPid, <<"test">>, <<"role">>, Docs),
    file:write_file("test.log", io_lib:format("insert_first_batch: ~p", [Result])),
    insert_first_batch(ConnPid, NextCur, min(NextCur + 100, Max), Max).
generate_insert_docs_for_pool(Cur, Max, DocsAcc) when Cur >= Max ->
    DocsAcc;
generate_insert_docs_for_pool(Cur, Max, DocsAcc) ->
    CurStr = integer_to_binary(Cur),
    Doc = #{
        <<"_id">> => Cur,
        <<"id">> => Cur,
        <<"name">> => <<"name_", CurStr/binary>>,
        <<"exp">> => Cur + 0.1
    },
    generate_insert_docs_for_pool(Cur + 1, Max, [Doc | DocsAcc]).

find_pool_test() ->
    SelectorDoc = #{
        <<"id">> => #{
            <<"$gt">> => 0
        }
    },
    SortDoc = #{
        <<"id">> => -1
    },
    ProjectDoc = #{
        <<"id">> => 1,
        <<"exp">> => 1,
        <<"name">> => 1,
        <<"_id">> => 1
    },
    {ok, FirstBatchs, CursorPid} = mc_pool_api:find(?MONGO_TEST_POOL, <<"test">>, <<"role">>, SelectorDoc, SortDoc, ProjectDoc, 0, 10000),
    file:write_file("test.log", io_lib:format("~p~n~p", [CursorPid, FirstBatchs])),
    next_pool_doc(CursorPid, 100, 10000, 100),
    mc_cursor:close(CursorPid).

next_pool_doc(_CursorPid, CurIdx, MaxIdx, _BatchSize) when CurIdx >= MaxIdx ->
    ok;
next_pool_doc(CursorPid, CurIdx, MaxIdx, BatchSize) ->
    case mc_cursor:next(CursorPid, BatchSize) of
        {ok, []} -> ok;
        {ok, NextBatchs} ->
            file:write_file("test.log", io_lib:format("~p~n~n~p", [BatchSize, NextBatchs])),
            next_pool_doc(CursorPid, CurIdx + length(NextBatchs), MaxIdx, BatchSize);
        _ -> ok
    end.